/**
 * @file config_manager.c
 * @brief 基于cJSON的配置管理器实现
 * @details 实现JSON配置文件的加载、解析、查询和修改功能
 * @author 开发者
 * @date 2024
 * @version 1.0.0
 */

#include "config_manager.h"
#include "../../log/logger.h"
#include "../../third_party/cJSON/cJSON.h"
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

/**
 * @name 内部函数声明
 * @{
 */
static char* read_file_content(const char *filename, size_t *size);     /**< 读取文件内容 */
static cJSON* find_nested_object(cJSON *json, const char *path);        /**< 查找嵌套对象 */
static int create_nested_path(cJSON *json, const char *path);           /**< 创建嵌套路径 */
/** @} */

/**
 * @brief 初始化配置管理器
 * @details 初始化配置管理器，设置配置目录并加载所有配置文件
 * @param manager 配置管理器指针
 * @param config_dir 配置目录路径
 * @return 成功返回0，失败返回-1
 */
int config_manager_init(config_manager_t *manager, const char *config_dir) {
    // 1. 参数验证
    if (!manager || !config_dir) {
        LOG_ERROR("参数错误");
        return -1;
    }
    
    // 2. 初始化结构体
    memset(manager, 0, sizeof(config_manager_t));
    
    // 3. 复制配置目录路径
    manager->config_dir = strdup(config_dir);
    if (!manager->config_dir) {
        LOG_ERROR("内存分配失败");
        return -1;
    }
    
    // 4. 加载设备配置文件
    manager->device_config = config_manager_load_file(manager, "device_config.json");
    if (!manager->device_config) {
        LOG_WARN("无法加载设备配置文件");
    }
    
    // 5. 加载物模型文件
    manager->thing_model = config_manager_load_file(manager, "models/thing_model.json");
    if (!manager->thing_model) {
        LOG_WARN("无法加载物模型文件");
    }
    
    // 6. 加载消息模板文件
    manager->message_templates = config_manager_load_file(manager, "templates/message_templates.json");
    if (!manager->message_templates) {
        LOG_WARN("无法加载消息模板文件");
    }
    
    // 7. 设置初始化标志
    manager->initialized = true;
    
    // 8. 记录初始化完成日志
    LOG_INFO("配置管理器初始化完成，配置目录: %s", config_dir);
    return 0;
}

// 清理配置管理器
void config_manager_cleanup(config_manager_t *manager) {
    if (!manager) {
        return;
    }
    
    if (manager->device_config) {
        cJSON_Delete(manager->device_config);
    }
    
    if (manager->thing_model) {
        cJSON_Delete(manager->thing_model);
    }
    
    if (manager->message_templates) {
        cJSON_Delete(manager->message_templates);
    }
    
    if (manager->config_dir) {
        free(manager->config_dir);
    }
    
    LOG_INFO("配置管理器清理完成");
}

// 加载配置文件
cJSON* config_manager_load_file(config_manager_t *manager, const char *filename) {
    if (!manager || !filename) {
        return NULL;
    }
    
    char full_path[512];
    snprintf(full_path, sizeof(full_path), "%s/%s", manager->config_dir, filename);
    
    size_t content_size;
    char *content = read_file_content(full_path, &content_size);
    if (!content) {
        LOG_ERROR("无法读取配置文件: %s", full_path);
        return NULL;
    }
    
    cJSON *json = cJSON_Parse(content);
    free(content);
    
    if (!json) {
        LOG_ERROR("JSON解析失败: %s", full_path);
        return NULL;
    }
    
    LOG_INFO("配置文件加载成功: %s", full_path);
    return json;
}

// 保存配置文件
int config_manager_save_file(config_manager_t *manager, cJSON *json, const char *filename) {
    if (!manager || !json || !filename) {
        return -1;
    }
    
    char full_path[512];
    snprintf(full_path, sizeof(full_path), "%s/%s", manager->config_dir, filename);
    
    char *json_string = cJSON_Print(json);
    if (!json_string) {
        LOG_ERROR("JSON序列化失败");
        return -1;
    }
    
    FILE *file = fopen(full_path, "w");
    if (!file) {
        LOG_ERROR("无法打开文件进行写入: %s", full_path);
        free(json_string);
        return -1;
    }
    
    size_t written = fwrite(json_string, 1, strlen(json_string), file);
    fclose(file);
    free(json_string);
    
    if (written != strlen(json_string)) {
        LOG_ERROR("文件写入不完整: %s", full_path);
        return -1;
    }
    
    LOG_INFO("配置文件保存成功: %s", full_path);
    return 0;
}

/**
 * @brief 获取字符串配置值
 * @details 从JSON对象中获取指定键的字符串值，如果不存在则返回默认值
 * @param json JSON对象指针
 * @param key 配置键名
 * @param default_value 默认值
 * @return 配置值或默认值
 */
const char* config_get_string(cJSON *json, const char *key, const char *default_value) {
    // 1. 参数验证
    if (!json || !key) {
        return default_value;
    }
    
    // 2. 获取配置项
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (!item || !cJSON_IsString(item)) {
        return default_value;
    }
    
    // 3. 返回字符串值
    return item->valuestring;
}

/**
 * @brief 获取整数配置值
 * @details 从JSON对象中获取指定键的整数值，如果不存在则返回默认值
 * @param json JSON对象指针
 * @param key 配置键名
 * @param default_value 默认值
 * @return 配置值或默认值
 */
int config_get_int(cJSON *json, const char *key, int default_value) {
    // 1. 参数验证
    if (!json || !key) {
        return default_value;
    }
    
    // 2. 获取配置项
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (!item || !cJSON_IsNumber(item)) {
        return default_value;
    }
    
    // 3. 返回整数值
    return item->valueint;
}

/**
 * @brief 获取布尔配置值
 * @details 从JSON对象中获取指定键的布尔值，如果不存在则返回默认值
 * @param json JSON对象指针
 * @param key 配置键名
 * @param default_value 默认值
 * @return 配置值或默认值
 */
bool config_get_bool(cJSON *json, const char *key, bool default_value) {
    // 1. 参数验证
    if (!json || !key) {
        return default_value;
    }
    
    // 2. 获取配置项
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (!item || !cJSON_IsBool(item)) {
        return default_value;
    }
    
    // 3. 返回布尔值
    return cJSON_IsTrue(item);
}

// 获取浮点数配置值
double config_get_double(cJSON *json, const char *key, double default_value) {
    if (!json || !key) {
        return default_value;
    }
    
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (!item || !cJSON_IsNumber(item)) {
        return default_value;
    }
    
    return item->valuedouble;
}

// 获取嵌套配置值
const char* config_get_nested_string(cJSON *json, const char *path, const char *default_value) {
    if (!json || !path) {
        return default_value;
    }
    
    cJSON *nested = find_nested_object(json, path);
    if (!nested || !cJSON_IsString(nested)) {
        return default_value;
    }
    
    return nested->valuestring;
}

// 设置字符串配置值
int config_set_string(cJSON *json, const char *key, const char *value) {
    if (!json || !key || !value) {
        return -1;
    }
    
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (item) {
        cJSON_SetValuestring(item, value);
    } else {
        cJSON_AddStringToObject(json, key, value);
    }
    
    return 0;
}

// 设置整数配置值
int config_set_int(cJSON *json, const char *key, int value) {
    if (!json || !key) {
        return -1;
    }
    
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (item) {
        cJSON_SetIntValue(item, value);
    } else {
        cJSON_AddNumberToObject(json, key, value);
    }
    
    return 0;
}

// 设置布尔配置值
int config_set_bool(cJSON *json, const char *key, bool value) {
    if (!json || !key) {
        return -1;
    }
    
    cJSON *item = cJSON_GetObjectItem(json, key);
    if (item) {
        cJSON_SetBoolValue(item, value);
    } else {
        cJSON_AddBoolToObject(json, key, value);
    }
    
    return 0;
}

// 设置嵌套配置值
int config_set_nested_string(cJSON *json, const char *path, const char *value) {
    if (!json || !path || !value) {
        return -1;
    }
    
    // 创建嵌套路径
    if (create_nested_path(json, path) != 0) {
        return -1;
    }
    
    cJSON *nested = find_nested_object(json, path);
    if (nested) {
        cJSON_SetValuestring(nested, value);
        return 0;
    }
    
    return -1;
}

// 检查配置项是否存在
bool config_has_key(cJSON *json, const char *key) {
    if (!json || !key) {
        return false;
    }
    
    return cJSON_HasObjectItem(json, key);
}

// 获取数组大小
int config_get_array_size(cJSON *json) {
    if (!json || !cJSON_IsArray(json)) {
        return 0;
    }
    
    return cJSON_GetArraySize(json);
}

// 获取数组元素
cJSON* config_get_array_item(cJSON *json, int index) {
    if (!json || !cJSON_IsArray(json)) {
        return NULL;
    }
    
    return cJSON_GetArrayItem(json, index);
}

// 添加数组元素
int config_add_array_item(cJSON *json, cJSON *item) {
    if (!json || !cJSON_IsArray(json) || !item) {
        return -1;
    }
    
    cJSON_AddItemToArray(json, item);
    return 0;
}

// 创建消息模板
cJSON* config_create_message_template(const char *template_name, const char **variables, int variable_count) {
    if (!template_name) {
        return NULL;
    }
    
    cJSON *template = cJSON_CreateObject();
    if (!template) {
        return NULL;
    }
    
    cJSON_AddStringToObject(template, "name", template_name);
    cJSON_AddStringToObject(template, "version", "V2.3");
    
    cJSON *vars = cJSON_CreateArray();
    if (vars && variables) {
        for (int i = 0; i < variable_count; i++) {
            cJSON_AddItemToArray(vars, cJSON_CreateString(variables[i]));
        }
        cJSON_AddItemToObject(template, "variables", vars);
    }
    
    return template;
}

// 填充消息模板
cJSON* config_fill_message_template(cJSON *template_json, const char **values, int value_count) {
    if (!template_json) {
        return NULL;
    }
    
    cJSON *result = cJSON_Duplicate(template_json, 1);
    if (!result) {
        return NULL;
    }
    
    cJSON *vars = cJSON_GetObjectItem(template_json, "variables");
    if (vars && cJSON_IsArray(vars) && values) {
        int var_count = cJSON_GetArraySize(vars);
        int fill_count = (value_count < var_count) ? value_count : var_count;
        
        for (int i = 0; i < fill_count; i++) {
            cJSON *var = cJSON_GetArrayItem(vars, i);
            if (var && cJSON_IsString(var)) {
                cJSON_SetValuestring(var, values[i]);
            }
        }
    }
    
    return result;
}

// 验证配置完整性
int config_validate(cJSON *json, const char **required_keys, int key_count) {
    if (!json || !required_keys || key_count <= 0) {
        return -1;
    }
    
    for (int i = 0; i < key_count; i++) {
        if (!cJSON_HasObjectItem(json, required_keys[i])) {
            LOG_ERROR("缺少必需的配置项: %s", required_keys[i]);
            return -1;
        }
    }
    
    return 0;
}

// 打印配置内容
void config_print(cJSON *json, const char *title) {
    if (!json) {
        return;
    }
    
    char *json_string = cJSON_Print(json);
    if (json_string) {
        if (title) {
            LOG_INFO("%s:", title);
        }
        LOG_INFO("%s", json_string);
        free(json_string);
    }
}

/**
 * @brief 读取文件内容
 * @details 读取指定文件的全部内容到内存中
 * @param filename 文件名
 * @param size 返回文件大小
 * @return 文件内容指针，失败返回NULL
 */
static char* read_file_content(const char *filename, size_t *size) {
    // 1. 打开文件
    FILE *file = fopen(filename, "r");
    if (!file) {
        return NULL;
    }
    
    // 2. 获取文件大小
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    if (file_size <= 0) {
        fclose(file);
        return NULL;
    }
    
    // 3. 分配内存
    char *content = malloc(file_size + 1);
    if (!content) {
        fclose(file);
        return NULL;
    }
    
    // 4. 读取文件内容
    size_t read_size = fread(content, 1, file_size, file);
    fclose(file);
    
    if (read_size != (size_t)file_size) {
        free(content);
        return NULL;
    }
    
    content[file_size] = '\0';
    *size = file_size;
    
    return content;
}

static cJSON* find_nested_object(cJSON *json, const char *path) {
    if (!json || !path) {
        return NULL;
    }
    
    char *path_copy = strdup(path);
    char *token = strtok(path_copy, ".");
    cJSON *current = json;
    
    while (token && current) {
        if (cJSON_IsObject(current)) {
            current = cJSON_GetObjectItem(current, token);
        } else {
            current = NULL;
        }
        token = strtok(NULL, ".");
    }
    
    free(path_copy);
    return current;
}

static int create_nested_path(cJSON *json, const char *path) {
    if (!json || !path) {
        return -1;
    }
    
    char *path_copy = strdup(path);
    char *token = strtok(path_copy, ".");
    cJSON *current = json;
    
    while (token) {
        cJSON *next = cJSON_GetObjectItem(current, token);
        if (!next) {
            next = cJSON_CreateObject();
            if (!next) {
                free(path_copy);
                return -1;
            }
            cJSON_AddItemToObject(current, token, next);
        }
        current = next;
        token = strtok(NULL, ".");
    }
    
    free(path_copy);
    return 0;
}
